﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
 
namespace MagicCove
{
    //While it should work with out specifying the ref, it is done just in case to make sure
    //Base for the Special Effects
    //pF is the players field, oF is the oppenents field, targets is an list of the targets
    class sEBase : MagicStackItem
    {
        protected String sEName = "Ability Name";
        protected MagicCard parentCard;
        private iPBase iPC;//is playable class
        private bool countered;
        public sEBase(iPBase iPC)
        {
            iPC.ParentSE = this;
            this.iPC = iPC;
            countered = false;
        }
        public virtual void specialEffect()
        {
            throw new System.Exception("This function should never be called. (specialEffect base class)");
        }
        public virtual void removeSpecialEffect()
        {//This allows iP to remove a sE if a status based iP is no longer met. (for example Metalcraft).
            //Not all sE must implement this, only those who can correspond to a temporary effect. (like boosting attack).
            throw new System.Exception("This function should never be called. (removeSpecialEffect base class)");
        }

        public String ItemName
        {
            get
            {
                return sEName + " (" + parentCard.ItemName + ")";
            }
        }
        public MagicCard ParentCard
        {
            get
            {
                return parentCard;
            }
            set
            {
                parentCard = value;
            }
        }
        public bool Countered
        {
            get
            {
                return this.countered;
            }
            set
            {
                this.countered = value;
            }
        }
        public bool IsPlayable
        {
            get
            {
                int[] tempFieldMana = (int[])parentCard.ParentField.Mana.Clone();
                int[] manaLeft = iPC.getManaLeft();
                foreach (int element in manaLeft)
                    if (element < 0)
                        return false;
                if (!iPC.isPlayable())
                    return false;
                for (int i = 0; i < 6; i++)//if the field has changed we must rebalance. (a sE added mana is the reason for this)
                {
                    parentCard.ParentField.Mana[i] = parentCard.ParentField.Mana[i] - tempFieldMana[i] + manaLeft[i];
                }
                return true;
            }
        }
        public iPBase IPClass
        {
            get
            {
                return this.iPC;
            }
        }
        public void popedFromStack()
        {//activates the ability
            specialEffect();
        }
    }
    #region Magic Card Special Effect Overides
    #region Keyword Effects
    interface KeywordEffect
    {
        bool Has //returns whether card actively has the keyword
        {
            get;
        }
    }
    class sEBattleCry : sEBase
    {
        public sEBattleCry(iPBase iPC)
            : base(iPC) { sEName = "Battle Cry"; }
        public override void specialEffect()
        {
            foreach (MagicCard attackingCreature in ParentCard.ParentField.ParentGameForm.AttackingCreatures)
                if (attackingCreature != parentCard)
                    attackingCreature.TempAttack++;
        }
    }
    class sECreateTokens : sEBase
    {
        MagicCard tokenCard;
        int copies;
        public sECreateTokens(iPBase iPC, MagicCard tokenCard, int copies )
            : base(iPC) { this.tokenCard = tokenCard; this.copies = copies; }
    }
    class sEDefender : sEBase
    {
        public sEDefender(iPBase iPC)
            : base(iPC) { }
        public override void specialEffect()
        {
            //we can fake defender by always giving the creature sumonning sickness so it cannot attack
            parentCard.summoningSickness = true;
        }
    }
    #endregion
    #region General Effects
    class sEDrawCard : sEBase
    {
        public sEDrawCard(iPBase iPC)
            : base(iPC) { }
        override public void specialEffect()
        {
            if (parentCard.Location == CurrentLocation.Stack && parentCard.LocationGoing == CurrentLocation.Field)
                parentCard.ParentField.drawCard(0);
        }
    }
    #endregion
    #region General Abilities
    class sEDestroyTarget : sEBase
    {
        public sEDestroyTarget(iPBase iPC)
            : base(iPC) { }
        public override void specialEffect()
        {
            parentCard.targets[0].LocationGoing = CurrentLocation.Graveyard;
        }
    }
    class sEGainLife : sEBase
    {
        int lifeGainAmount;
        bool attack;
        bool defense;
        bool convertedManaCost;
        public sEGainLife(iPBase iPC, int lifeGainAmount)
            : base(iPC) { this.lifeGainAmount = lifeGainAmount; attack = false; defense = false; convertedManaCost = false;}
        public sEGainLife(iPBase iPC, bool attack, bool defense, bool convertedManaCost) //if the mana is based on a dynamic value
            : base(iPC) { this.lifeGainAmount = 0; this.attack = attack; this.defense = defense; this.convertedManaCost = convertedManaCost; }
        public override void specialEffect()
        {
            if (lifeGainAmount != 0)
                parentCard.ParentField.life += lifeGainAmount;
            //note we assume it is for all targets summed. if the card can only target one thing iP will make sure that the list of targets.Count == 1
            if (attack)
                foreach (MagicCard mC in parentCard.targets)
                    parentCard.ParentField.life += mC.Attack;
            if (defense)
                foreach (MagicCard mC in parentCard.targets)
                    parentCard.ParentField.life += mC.Defense;
            if (attack)
                foreach (MagicCard mC in parentCard.targets)
                    parentCard.ParentField.life += mC.ConvertedManaCost;
        }
    }
    //need another for sEMoveTarget
    class sEMoveToDeck : sEBase
    {
        bool topOfDeck; //if false then bottom of deck
        bool shuffleDeck; //suffle deck after placing? (if this is true then doesn't matter where it was placed)
        //assumes you can choose the order it goes into the deck (if shuffle is false)
        public sEMoveToDeck(iPBase iPC, bool topOfDeck, bool shuffleDeck)
            : base(iPC) { this.topOfDeck = topOfDeck; this.shuffleDeck = shuffleDeck; }
        public override void specialEffect()
        {
            //prompt user to select order of cards
            if (!shuffleDeck)
            {
                System.Windows.Forms.MessageBox.Show("Please reorder the target list in the order you would like it to go on the deck. The topmost card of the list will be the card closest to the top of the deck.", "Reorder Targets Instructions");
                parentCard.targets = GameFunctions.reorderMCList(parentCard.targets);
            }
            if (topOfDeck)
                for (int i = parentCard.targets.Count - 1; i >= 0; i--)//then do it backwards so the get there in the right order
                    parentCard.ParentField.ParentGameForm.moveCardToDeck(parentCard.targets[i], topOfDeck, shuffleDeck);
            else
                foreach (MagicCard mC in parentCard.targets)
                    parentCard.ParentField.ParentGameForm.moveCardToDeck(mC, topOfDeck, shuffleDeck);
        }
    }
    class sEPlusXPlusY : sEBase
    {
        int attackBonus;
        int defenseBonus;
        public sEPlusXPlusY(iPBase iPC, int attackBonus, int defenseBonus)
            : base(iPC) { this.attackBonus = attackBonus; this.defenseBonus = attackBonus; }
        public override void specialEffect()
        {
            parentCard.Attack += attackBonus;
            parentCard.TempAttack += attackBonus;
            parentCard.Defense += defenseBonus;
            parentCard.TempDefense += defenseBonus;
        }
        public override void removeSpecialEffect()
        {
            parentCard.Attack -= attackBonus;
            parentCard.TempAttack -= attackBonus;
            parentCard.Defense -= defenseBonus;
            parentCard.TempDefense -= defenseBonus;
        }
    }
    class sEPutMinusOneCounters : sEBase
    {
        int amountOfCounters;
        public sEPutMinusOneCounters(iPBase iPC, int numberOfCounters)
            : base(iPC) { this.amountOfCounters = numberOfCounters; }
        public override void specialEffect()
        {
            foreach (MagicCard mC in parentCard.targets)
                mC.MinusOneCounters++;
        }
    }
    #endregion
    #region Artifacts (0)
    #endregion
    #region Creatures (1)
    #endregion
    #region Enchantments (2)
    #endregion
    #region Instants (3)
    #endregion
    #region Lands (4)
    //lands do not the if check anymore, that is handled by isPlayable
    class sEPlains : sEBase
    {
        public sEPlains(iPBase iPC)
            : base(iPC) { }
        override public void specialEffect()
        {
            parentCard.ParentField.Mana[1]++;
            parentCard.tapped = true;
        }
    }
    class sEIsland : sEBase
    {
        public sEIsland(iPBase iPC)
            : base(iPC) { }
        override public void specialEffect()
        {
            parentCard.ParentField.Mana[2]++;
            parentCard.tapped = true;
        }
    }
    class sESwamp : sEBase
    {
        public sESwamp(iPBase iPC)
            : base(iPC) { }
        override public void specialEffect()
        {
            parentCard.ParentField.Mana[3]++;
            parentCard.tapped = true;
        }
    }
    class sEMountain : sEBase
    {
        public sEMountain(iPBase iPC)
            : base(iPC) { }
        override public void specialEffect()
        {
            parentCard.ParentField.Mana[4]++;
            parentCard.tapped = true;
        }
    }
    class sEForest : sEBase
    {
        public sEForest(iPBase iPC)
            : base(iPC) { }
        override public void specialEffect()
        {
            parentCard.ParentField.Mana[5]++;
            parentCard.tapped = true;
        }
    }
    #endregion
    #region Planeswalkers (5)
    #endregion
    #region Sorcery (6)
    #endregion
    #region Tribal (7)
    #endregion
    #endregion
}
